package com.vhall.component.service.tag.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vhall.component.dao.room.RoomMapper;
import com.vhall.component.dao.tag.PageChannelMapper;
import com.vhall.component.entity.room.entity.RoomsEntity;
import com.vhall.component.entity.subject.enums.StatusEnum;
import com.vhall.component.entity.tag.PageChannelEntity;
import com.vhall.component.entity.tag.vo.*;
import com.vhall.component.plugin.common.enums.DeleteStatusEnum;
import com.vhall.component.plugin.common.utils.BeanCopyUtil;
import com.vhall.component.service.tag.PageChannelService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.assertj.core.util.Preconditions;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author vhall
 * @description 针对表【page_channel(页面频道表)】的数据库操作Service实现
 * @createDate 2023-04-12 17:12:40
 */
@Slf4j
@Service
public class PageChannelServiceImpl extends ServiceImpl<PageChannelMapper, PageChannelEntity> implements PageChannelService {

    private static final int PID = 0;

    @Resource
    private RoomMapper roomMapper;

    @Override
    public Boolean saveInfo(PageChannelReqVO reqVO) {

        basicVerification(reqVO);

        PageChannelEntity pageChannelEntity = new PageChannelEntity();
        BeanCopyUtil.copy(reqVO, pageChannelEntity);

        // 设置顺序
        Integer pid = reqVO.getPid();

        pageChannelEntity.setSort(getSortByPid(pid));
        baseMapper.insert(pageChannelEntity);
        return true;
    }

    private int getSortByPid(Integer pid) {
        LambdaQueryWrapper<PageChannelEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(PageChannelEntity::getPid, pid == null ? 0 : pid);
        wrapper.ne(PageChannelEntity::getId, 1);
        wrapper.eq(PageChannelEntity::getIsDelete, DeleteStatusEnum.NO_DELETE.getStatus());
        wrapper.orderByDesc(PageChannelEntity::getSort).last("LIMIT 1");

        PageChannelEntity pageChannelEntity = baseMapper.selectOne(wrapper);
        return pageChannelEntity != null ? pageChannelEntity.getSort() + 1 : 1;
    }


    @Override
    public Boolean updateInfo(PageChannelReqVO reqVO) {
        Preconditions.checkArgument(reqVO.getId() != null, "id不能为空！");

        basicVerification(reqVO);

        LambdaUpdateWrapper<PageChannelEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(PageChannelEntity::getId, reqVO.getId());

        // 判断是否更改了父类
        PageChannelEntity pageChannelEntity1 = baseMapper.selectById(reqVO.getId());
        if (reqVO.getPid() != null && !pageChannelEntity1.getPid().equals(reqVO.getPid())) {
            int sort = getSortByPid(reqVO.getPid());
            wrapper.set(PageChannelEntity::getSort, sort);
        }

        wrapper.set(PageChannelEntity::getChannelName, reqVO.getChannelName());
        wrapper.set(PageChannelEntity::getEngName, reqVO.getEngName());
        wrapper.set(PageChannelEntity::getUrl, reqVO.getUrl());
        wrapper.set(PageChannelEntity::getRemark, reqVO.getRemark());
        wrapper.set(PageChannelEntity::getUpdatedAt, LocalDateTime.now());
        wrapper.set(PageChannelEntity::getLimitedTimeFree, reqVO.getLimitedTimeFree());
        wrapper.set(PageChannelEntity::getChannelStatus, reqVO.getChannelStatus());
        wrapper.set(PageChannelEntity::getChannelShow, reqVO.getChannelShow());

        baseMapper.update(null, wrapper);
        return true;
    }


    @Override
    public Boolean delete(Integer id) {

        Preconditions.checkArgument(id != 1 && id != 2, "当前频道不能删除");

        judgeAssociatedRoom(id);

        LambdaUpdateWrapper<PageChannelEntity> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(PageChannelEntity::getId, id)
                .set(PageChannelEntity::getDeletedAt, LocalDateTime.now())
                .set(PageChannelEntity::getIsDelete, DeleteStatusEnum.DELETE.getStatus());

        baseMapper.update(null, wrapper);


        return true;
    }

    /**
     * 判断是否有关联房间
     *
     * @param id
     */
    private void judgeAssociatedRoom(Integer id) {
        // 获取当前频道下面的所有子频道
        Set<Integer> childIds = new HashSet<>();
        childIds.add(id);

        List<PageChannelEntity> allChannel = getAllChannel();
        if (CollectionUtil.isNotEmpty(allChannel)) {
            getAllChildList(id, allChannel, childIds);
        }

        List<Integer> idsList = new ArrayList<>(childIds);


        // 判断是否有关联
        LambdaQueryWrapper<RoomsEntity> queryList = Wrappers.lambdaQuery();
        queryList.in(RoomsEntity::getPageChannelId, idsList);
        List<RoomsEntity> roomsEntities = roomMapper.selectList(queryList);
        Preconditions.checkArgument(CollectionUtil.isEmpty(roomsEntities), "当前频道或子频道有房间关联！");
    }

    @Override
    public List<PageChannelRspVO> getInfo(List<Integer> ids) {
        List<PageChannelEntity> pageChannelEntities = baseMapper.selectBatchIds(ids);
        List<PageChannelRspVO> pageChannelRspVOS = BeanCopyUtil.batchCopy(pageChannelEntities, PageChannelRspVO::new);
        return pageChannelRspVOS;
    }

    @Override
    public List<PageChannelListRspVO> listInfo(PageChannelListReqVO reqVO) {
        List<PageChannelListRspVO> result = Lists.newArrayList();
        String keyword = reqVO.getKeyword();
        if (StringUtils.isBlank(keyword) && reqVO.getStatus() == null) {

            List<PageChannelEntity> allChannel = getAllChannel();

            if (CollectionUtil.isNotEmpty(allChannel)) {

                // 这是一级节点
                List<PageChannelEntity> pidZeroList = allChannel.stream().filter(e -> e.getPid().equals(PID)).collect(Collectors.toList());

                Map<Integer, List<PageChannelEntity>> groupByPidMap = allChannel.stream().collect(Collectors.groupingBy(PageChannelEntity::getPid));

                for (PageChannelEntity pidEntity : pidZeroList) {

                    List<PageChannelEntity> childrenList = groupByPidMap.get(pidEntity.getId());

                    PageChannelListRspVO pidVo = new PageChannelListRspVO();
                    BeanCopyUtil.copy(pidEntity, pidVo);
                    pidVo.setLevel(1);

                    result.add(pidVo);
                }
            }

        } else {
            LambdaQueryWrapper<PageChannelEntity> queryList = Wrappers.lambdaQuery();
            queryList.and(StringUtils.isNotBlank(keyword), wq -> wq.eq(PageChannelEntity::getId, keyword).or().like(PageChannelEntity::getChannelName, keyword));
            queryList.eq(reqVO.getStatus() != null, PageChannelEntity::getChannelStatus, reqVO.getStatus());

            queryList.eq(PageChannelEntity::getIsDelete, DeleteStatusEnum.NO_DELETE.getStatus());
            queryList.orderByDesc(PageChannelEntity::getUpdatedAt);
            List<PageChannelEntity> allChannel = baseMapper.selectList(queryList);
            result.addAll(BeanCopyUtil.batchCopy(allChannel, PageChannelListRspVO::new));
        }

        result = result.stream().sorted(Comparator.comparing(PageChannelListRspVO::getSort)).collect(Collectors.toList());
        return result;
    }

    private List<PageChannelEntity> getAllChannel() {
        LambdaQueryWrapper<PageChannelEntity> queryList = Wrappers.lambdaQuery();
        queryList.eq(PageChannelEntity::getIsDelete, DeleteStatusEnum.NO_DELETE.getStatus());
        queryList.orderByAsc(PageChannelEntity::getUpdatedAt);
        return baseMapper.selectList(queryList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean sortInfo(PageChannelSortReqVO reqVO) {

        Preconditions.checkArgument(CollectionUtil.isNotEmpty(reqVO.getIds()), "主键不能为空！");
        List<Integer> ids = reqVO.getIds();
        Integer firstId = ids.get(0);
        Integer secondId = ids.get(1);

        Preconditions.checkArgument(firstId != 1 && secondId != 1, "精选不参与排序！");

        List<PageChannelEntity> pageChannelEntities = baseMapper.selectBatchIds(reqVO.getIds());
        Preconditions.checkArgument(CollectionUtil.isNotEmpty(pageChannelEntities) && pageChannelEntities.size() == 2, "传入id有误！");

        Map<Integer, PageChannelEntity> channelEntityMap = pageChannelEntities.stream().collect(Collectors.toMap(PageChannelEntity::getId, e -> e));


        PageChannelEntity firstChannel = channelEntityMap.get(firstId);
        Integer firstSort = firstChannel.getSort();

        PageChannelEntity secondChannel = channelEntityMap.get(secondId);
        Integer secondSort = secondChannel.getSort();

        firstChannel.setSort(secondSort);
        firstChannel.setUpdatedAt(LocalDateTime.now());
        baseMapper.updateById(firstChannel);


        secondChannel.setSort(firstSort);
        secondChannel.setUpdatedAt(LocalDateTime.now());
        baseMapper.updateById(secondChannel);


        return true;
    }

    @Override
    public Boolean changeInfo(PageChannelChangeReqVO reqVO, String status) {
        Preconditions.checkArgument(reqVO.getId() != null, "id不能为空！");
        Preconditions.checkArgument(reqVO.getId() != 1, "精选不能编辑！");

        PageChannelEntity pageChannelEntity = new PageChannelEntity();
        pageChannelEntity.setUpdatedAt(LocalDateTime.now());
        // 打开，关闭标记位，默认关闭false
//        boolean openOrCloseFlag = false;
        if ("status".equals(status)) {
            pageChannelEntity.setChannelStatus(reqVO.getChannelStatus());
//            openOrCloseFlag = reqVO.getChannelStatus() != null && reqVO.getChannelStatus() == 1;
        } else if ("show".equals(status)) {
            pageChannelEntity.setChannelShow(reqVO.getChannelShow());
//            openOrCloseFlag = reqVO.getChannelShow() != null && reqVO.getChannelShow() == 1;
        }

        change(Collections.singleton(reqVO.getId()), pageChannelEntity);

        // 查询所有信息
//        List<PageChannelEntity> allChannel = getAllChannel();
//        if (CollectionUtil.isNotEmpty(allChannel)) {
//
//            Set<Integer> parentIds = new TreeSet<>();
//            getAllParentList(reqVO.getId(), allChannel, parentIds);
//            log.info(MessageFormat.format("【{1}】 所有父节点：【{0}】", parentIds.toString(), reqVO.getId()));
//
//            Set<Integer> childIds = new TreeSet<>();
//            getAllChildList(reqVO.getId(), allChannel, childIds);
//            log.info(MessageFormat.format("【{1}】 所有子节点：【{0}】", childIds.toString(), reqVO.getId()));
//
//            if (openOrCloseFlag) {
//                // 开启    父级打开时，下属子级不全部联动，例：1级打开，2级和3级需要单独打开子级打开时，父级自动打开，例：3级打开，所属的2级和1级需要同时打开
//                childIds.remove(reqVO.getId());
//                if (CollectionUtil.isNotEmpty(childIds)) {
//                    change(Collections.singleton(reqVO.getId()), pageChannelEntity);
//                } else {
//                    change(parentIds, pageChannelEntity);
//                }
//            } else {
//                //关闭
//            }
//
//
//        }

        return true;
    }

    @Override
    public List<PageChannelListRspVO> listAllInfo(PageChannelListReqVO reqVO) {
        LambdaQueryWrapper<PageChannelEntity> queryList = Wrappers.lambdaQuery();

        queryList.and(StringUtils.isNotBlank(reqVO.getKeyword()), wq -> wq.likeRight(PageChannelEntity::getId, reqVO.getKeyword()).or().likeRight(PageChannelEntity::getChannelName, reqVO.getKeyword()));
        queryList.eq(PageChannelEntity::getIsDelete, DeleteStatusEnum.NO_DELETE.getStatus());
        if (reqVO.getStatus() != null && !reqVO.getStatus().equals(-1)) {
            // 传 -1 启用，不起用，显示，不显示都不起作用
            queryList.eq(PageChannelEntity::getChannelStatus, StatusEnum.OPEN.getValue());
            queryList.eq(reqVO.getChannelShow() != null, PageChannelEntity::getChannelShow, StatusEnum.OPEN.getValue());
        }
        queryList.orderByDesc(PageChannelEntity::getUpdatedAt);
        List<PageChannelEntity> allChannel = baseMapper.selectList(queryList);

        List<PageChannelEntity> list = new ArrayList<>();
        if (reqVO.getLevel() == null) {
            // 查询所有
            list = allChannel;
        } else {

            List<PageChannelEntity> one = allChannel.stream().filter(e -> e.getPid() == 0).collect(Collectors.toList());

            if (reqVO.getLevel() == 1) {
                list = one;
            } else if (reqVO.getLevel() == 2) {
                List<Integer> oneIdlist = one.stream().map(PageChannelEntity::getId).collect(Collectors.toList());
                list = allChannel.stream().filter(e -> oneIdlist.contains(e.getPid())).collect(Collectors.toList());
            }
        }
        list = list.stream().sorted(Comparator.comparing(PageChannelEntity::getSort)).collect(Collectors.toList());

        if ("adver".equals(reqVO.getUse())) {
            list = list.stream().filter(e -> !"兴证学堂".equals(e.getChannelName())).collect(Collectors.toList());
        }

        return BeanCopyUtil.batchCopy(list, PageChannelListRspVO::new);

    }


    /**
     * 获取当前节点的所有子节点
     */
    private void getAllChildList(Integer id, List<PageChannelEntity> allChannel, Set<Integer> childIds) {
        childIds.add(id);

        Map<Integer, List<PageChannelEntity>> groupByPidMap = allChannel.stream().collect(Collectors.groupingBy(PageChannelEntity::getPid));
        List<PageChannelEntity> childLists = groupByPidMap.get(id);
        if (CollectionUtil.isNotEmpty(childLists)) {
            for (PageChannelEntity childList : childLists) {
                getAllChildList(childList.getId(), allChannel, childIds);
            }
        }

    }

    /**
     * 获取当前节点所有的父节点
     */
    private void getAllParentList(Integer id, List<PageChannelEntity> allChannel, Set<Integer> result) {
        result.add(id);
        PageChannelEntity currentIdEntity = allChannel.stream().filter(e -> e.getId().equals(id)).collect(Collectors.toList()).get(0);
        if (!currentIdEntity.getPid().equals(PID)) {
            result.add(currentIdEntity.getPid());
            getAllParentList(currentIdEntity.getPid(), allChannel, result);

        }

    }

    private void change(Set<Integer> id, PageChannelEntity pageChannelEntity) {
        LambdaUpdateWrapper<PageChannelEntity> wrapper = Wrappers.lambdaUpdate();
        wrapper.in(PageChannelEntity::getId, id);
        baseMapper.update(pageChannelEntity, wrapper);
    }


    private void basicVerification(PageChannelReqVO reqVO) {
        LambdaQueryWrapper<PageChannelEntity> queryName = Wrappers.lambdaQuery();
        queryName.eq(PageChannelEntity::getChannelName, reqVO.getChannelName());
        queryName.eq(PageChannelEntity::getIsDelete, DeleteStatusEnum.NO_DELETE.getStatus());
        PageChannelEntity pageChannelEntities = baseMapper.selectOne(queryName);
        Preconditions.checkArgument(pageChannelEntities == null || (reqVO.getId() != null && pageChannelEntities.getId().equals(reqVO.getId())), "该名称已存在，请重试");


        LambdaQueryWrapper<PageChannelEntity> queryEngName = Wrappers.lambdaQuery();
        queryEngName.eq(PageChannelEntity::getEngName, reqVO.getEngName());
        queryEngName.eq(PageChannelEntity::getIsDelete, DeleteStatusEnum.NO_DELETE.getStatus());
        PageChannelEntity entities = baseMapper.selectOne(queryEngName);
        Preconditions.checkArgument(entities == null || (reqVO.getId() != null && entities.getId().equals(reqVO.getId())), "该标识已存在，请重试");

        if (reqVO.getPid() != null && reqVO.getPid() != 0) {
            if (reqVO.getPid() == 2) {
                Preconditions.checkArgument(StringUtils.isNotBlank(reqVO.getUrl()), "频道封面不能为空！");
            }
            Preconditions.checkArgument(StringUtils.isNotBlank(reqVO.getRemark()), "频道说明不能为空！");

            LambdaQueryWrapper<PageChannelEntity> queryName2 = Wrappers.lambdaQuery();
            queryName2.eq(PageChannelEntity::getId, reqVO.getPid());
            PageChannelEntity pageChannelEntity = baseMapper.selectOne(queryName2);
            Preconditions.checkArgument(pageChannelEntity.getPid() == 0, "目前仅支持到二级频道");

        }

    }
}




